#include "ConditionalVariable.h"
#include "SharedPtr.h"
#include "../stream/StringTools.h"
#include <stdexcept>

DEF_BEG_LIBTOOLS

CConditionalVariable::CConditionalVariable() :_cond(0)
{
	_cond = ShareApi::CreateCondVariable();
	if (_cond == 0)
	{
		SharedPtr<TCHAR> ec(ShareApi::Global_GetLastError(), &ShareApi::Global_FreeMem);
#if defined(UNICODE) || defined(_UNICODE)
			throw std::runtime_error(unicode_to_gbk(std::wstring(ec.Get())).c_str());
#else
			throw std::runtime_error(ec.Get());
#endif
	}
}

CConditionalVariable::~CConditionalVariable()
{
	ShareApi::CloseConditionVariable(_cond);
	_cond = 0;
}

wt_status CConditionalVariable::Wait(unsigned int pred, CMutexBase* mutex)
{
	wt_status s = wt_notimeout;
	DWORD status = ShareApi::WaitConditionVariable(_cond, mutex->Handle(), pred);
	if (status == WAIT_FAILED) s = wt_abort;
	else if (status == WAIT_TIMEOUT) s = wt_timeout;

	return s;
}

wt_status CConditionalVariable::WaitForever(CMutexBase* mutex)
{
	wt_status s = wt_notimeout;
	DWORD status = ShareApi::WaitConditionVariable(_cond, mutex->Handle(), INFINITE);
	if (status == WAIT_FAILED) s = wt_abort;
	else if (status == WAIT_TIMEOUT) s = wt_timeout;

	return s;
}

void CConditionalVariable::NotifyOne()
{
	ShareApi::NotifyCondVariable(_cond);
}

void CConditionalVariable::NotifyAll()
{
	ShareApi::NotifyAllCondVariable(_cond);
}

DEF_END_LIBTOOLS